package com.qingzhuge.common.utils;

import com.alibaba.fastjson.JSON;
import com.qingzhuge.common.Constants;
import com.qingzhuge.exception.ServiceException;
import com.qingzhuge.interfaces.ISysUser;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.WebUtils;

import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;

/**
 * @author : zero.xiao
 * @description : Web层辅助类
 * @modified :
 */
@Slf4j
@UtilityClass
public class WebUtil {
    public void writer(ServletResponse response, Object obj) {
        try {
            response.setCharacterEncoding(Constants.DEFAULT_ENCODING);
            response.setContentType("text/html;CHARSET=UTF-8");
            PrintWriter out = response.getWriter();
            if (obj == null) {
                out.print("{}");
            } else {
                if (obj instanceof ResponseEntity) {
                    ResponseEntity responseEntity = (ResponseEntity) obj;
                    Object body = responseEntity.getBody();
                    out.print(JSON.toJSONString(body));
                } else {
                    out.print(JSON.toJSONString(obj));
                }
            }
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 返回json
     *
     * @param response    HttpServletResponse
     * @param result      结果对象
     * @param contentType contentType
     */
    public void writerJson(HttpServletResponse response, Object result, String contentType) {
        response.setCharacterEncoding(Constants.DEFAULT_ENCODING);
        response.setContentType(contentType);
        try (PrintWriter out = response.getWriter()) {
            out.append(JSON.toJSONString(result));
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 读取json请求的数据
     *
     * @param request HttpServletRequest
     * @return Map
     */
    public HashMap<String, Object> getJsonByRequestPayload(HttpServletRequest request) {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader;
        char[] buff = new char[1024];
        int len;
        try {
            reader = request.getReader();
            while ((len = reader.read(buff)) != -1) {
                sb.append(buff, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return JSON.parseObject(sb.toString(), HashMap.class);
    }

    public HttpServletRequest getRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (null == requestAttributes) {
            return null;
        }
        return ((ServletRequestAttributes) requestAttributes).getRequest();
    }

    public HttpServletResponse getResponse() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            return requestAttributes.getResponse();
        }
        return null;
    }

    public HttpSession getSession() {
        if (null == getRequest()) {
            return null;
        }
        return getRequest().getSession();
    }

    public Object getSessionAttribute(String key) {
        HttpSession session = getSession();
        if (null == session) {
            return null;
        }
        return session.getAttribute(key);
    }

    public void setSessionAttribute(String key, Object val) {
        if (null != getSession()) {
            getSession().setAttribute(key, val);
        }
    }

    public void setKaptcha(String text) {
        WebUtil.setSessionAttribute(KAPTCHA_SESSION_KEY, text);
    }

    public String getKaptcha() {
        String kaptcha = (String) getSessionAttribute(KAPTCHA_SESSION_KEY);
        if (kaptcha == null) {
            throw new ServiceException("验证码已失效");
        }
        if (null != getSession()) {
            getSession().removeAttribute(KAPTCHA_SESSION_KEY);
        }
        return kaptcha;
    }

    /**
     * 获取指定Cookie的值
     *
     * @param cookieName cookie名字
     * @return String
     */
    public String getCookieValue(String cookieName) {
        HttpServletRequest request = WebUtil.getRequest();
        if (request != null) {
            Cookie cookie = WebUtils.getCookie(request, cookieName);
            if (cookie != null) {
                return cookie.getValue();
            }
        }
        return null;
    }

    /**
     * 获取当前用户
     */
    public ISysUser getSysUser() {
        try {
            return (ISysUser) getSessionAttribute(ISysUser.SESSION_USER_ENTITY);
        } catch (Exception e) {
            log.error("{}", e);
        }
        return null;
    }

    public Long getSysUserId() {
        ISysUser user = getSysUser();
        if (user == null) {
            return (Long) getSessionAttribute(ISysUser.SESSION_USER_ENTITY_ID);
        } else {
            return user.getId();
        }
    }


    /**
     * 获得参数Map
     *
     * @param request HttpServletRequest
     * @return Map
     */
    public Map<String, Object> getParameterMap(HttpServletRequest request) {
        return WebUtils.getParametersStartingWith(request, null);
    }


    private void readerData(HttpServletRequest request, StringBuilder wholeStr) {
        String str;
        try {
            BufferedReader br = request.getReader();
            while ((str = br.readLine()) != null) {
                wholeStr.append(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 设置文件名
     */
    public void setResponseFileName(HttpServletRequest request, HttpServletResponse response,
                                           String displayName) {
        String userAgent = request.getHeader("User-Agent");
        boolean isie = false;
        if (userAgent != null && userAgent.toLowerCase().contains("msie")) {
            isie = true;
        }
        String displayName2;
        try {
            if (isie) {
                displayName2 = URLEncoder.encode(displayName, Constants.DEFAULT_ENCODING);
                // 修正URLEncoder将空格转换成+号的BUG
                displayName2 = displayName2.replaceAll("\\+", "%20");

                response.setHeader("Content-Disposition", "attachment;filename=" + displayName2);
            } else {
                displayName2 = new String(displayName.getBytes(Constants.DEFAULT_ENCODING), "ISO8859-1");
                // firefox空格截断
                response.setHeader("Content-Disposition", "attachment;filename=\"" + displayName2 + "\"");
            }
            String extStr = displayName2.substring(displayName2.indexOf(".") + 1);
            if ("xls".equalsIgnoreCase(extStr)) {
                response.setContentType("application/vnd.ms-excel CHARSET=UTF-8");
            } else {
                response.setContentType("application/octet-stream");
            }
        } catch (UnsupportedEncodingException e) {
            log.error("设置文件名发生错误", e);
        }
    }

    /**
     * 判断是否是白名单
     */
    public boolean isWhiteRequest(String url, int size, List<String> whiteUrls) {
        if (url == null || "".equals(url) || size == 0) {
            return true;
        } else {
            String refHost = url.toLowerCase();
            for (String urlTemp : whiteUrls) {
                if (refHost.contains(urlTemp.toLowerCase())) {
                    return true;
                }
            }
        }
        return false;
    }
}
